home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / mus / play / tracker_4_31.lzh / tracker / Arch / Hpux / alib_audio.c < prev    next >
C/C++ Source or Header  |  1995-05-15  |  9KB  |  372 lines

  1. /* hpalib_audio.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* port to hp using the Alib library */
  6. /* $Id: alib_audio.c,v 1.6 1995/05/15 12:19:17 espie Exp espie $
  7.  * $Log: alib_audio.c,v $
  8.  * Revision 1.6  1995/05/15  12:19:17  espie
  9.  * Hp port updated.
  10.  *
  11.  * Revision 1.5  1995/05/11  12:04:13  espie
  12.  * Stupid typo.
  13.  *
  14.  * Revision 1.4  1995/02/23  16:42:27  espie
  15.  * Began conversion to `common' model.
  16.  *
  17.  * Revision 1.3  1995/02/23  14:04:53  espie
  18.  * primary/secondary -> pps/pms.
  19.  *
  20.  * Revision 1.2  1995/02/21  17:57:55  espie
  21.  * Internal problem: RCS not working.
  22.  *
  23.  * Revision 1.1  1995/02/01  16:43:47  espie
  24.  * Initial revision
  25.  *
  26.  * Revision 1.1  1995/02/01  16:43:47  espie
  27.  * Initial revision
  28.  *
  29.  * Revision 1.2  1993/12/04  16:12:50  espie
  30.  * BOOL -> boolean.
  31.  *
  32.  * Revision 1.1  1993/07/14  16:33:41  espie
  33.  * Initial revision
  34.  *
  35.  */
  36.  
  37. #include "defs.h"
  38. #include "extern.h"
  39. #include <audio/Alib.h>
  40. #include <sys/socket.h>
  41. #include <netinet/in.h>
  42. #include <netinet/tcp.h>
  43.  
  44. ID("$Id: alib_audio.c,v 1.6 1995/05/15 12:19:17 espie Exp espie $")
  45.  
  46.  
  47. #define DEFAULT_BUFFERS
  48. #define DEFAULT_SET_MIX
  49. #define NEW_OUTPUT_SAMPLES_AWARE
  50. #include "Arch/common.c"
  51.  
  52. Audio    *audio;        /* AUDIO connection for Alib, like DISPLAY for Xlib */
  53.  
  54. LOCAL int freq;            /* which frequency do we want? */
  55.  
  56. AErrorHandler    prevHandler;    /* pointer to previous handler */    
  57.  
  58. LOCAL int    audioPaused = True;
  59. LOCAL int    streamSocket = 0;
  60. LOCAL int    pauseCount;
  61.  
  62. LOCAL short    *bufBase = NULL;
  63. LOCAL long    inLen;
  64.  
  65. LOCAL ATransID    xid;
  66.  
  67. LOCAL AConvertParams    *convert_params;
  68.  
  69. LOCAL AudioAttrMask    AttribsMask = 0, PlayAttribsMask = 0, ignoredMask = 0;
  70. LOCAL AudioAttributes    Attribs, PlayAttribs;
  71. LOCAL AGainEntry    gainEntry[4];    /* Need to be global since */
  72.                     /* PlayAttribs is global and it */
  73.                     /* contains a pointer to gainEntry */
  74. LOCAL SSPlayParams    streamParams;
  75.  
  76. extern char        use_speaker;
  77. extern AGainDB    volume;
  78.  
  79.  
  80. long myErrorHandler(audio, err_event)
  81.     Audio        *audio;
  82.     AErrorEvent    *err_event;
  83. {
  84.     char    errorbuf[132];
  85.  
  86.     AGetErrorText(audio, err_event->error_code, errorbuf, 131);
  87.      end_all(errorbuf);
  88. }
  89.  
  90.  
  91. void create_playstream()
  92. {
  93.     LOCAL SStream    audioStream;
  94.  
  95.     /*
  96.      * Initiate transaction.
  97.      */
  98.     xid = APlaySStream(audio, ~0, &PlayAttribs, &streamParams,
  99.                &audioStream, NULL);
  100.  
  101.     /*
  102.      * Create a stream socket.
  103.      */
  104.     streamSocket = socket(AF_INET, SOCK_STREAM, 0);
  105.     if(streamSocket < 0) {
  106.      end_all("Socket creation failed");
  107.     }
  108.   
  109.     /*
  110.      * Connect the stream socket to the audio stream port.
  111.      */
  112.     if (connect(streamSocket,
  113.         (struct sockaddr *)&audioStream.tcp_sockaddr,
  114.         sizeof(struct sockaddr_in)) < 0) {
  115.         end_all("Connect failed");
  116.     }
  117. }  
  118.  
  119.  
  120. int open_audio(f, s)
  121. int f;
  122. int s;
  123. {
  124.     char        *pSpeaker;
  125.     int            seekOffset, data_length;
  126.     AByteOrder        play_byte_order, byte_order;
  127.  
  128.  
  129.     audio = AOpenAudio(NULL, NULL);
  130.  
  131.     if (!audio) {
  132.         end_all("Error opening audio device");
  133.     }
  134.  
  135.     /* replace default error handler */
  136.     prevHandler = ASetErrorHandler(myErrorHandler);
  137.  
  138.     stereo = s;
  139.     if (stereo) {
  140.         Attribs.attr.sampled_attr.channels = 2;
  141.         AttribsMask |= (AttribsMask | ASChannelsMask);
  142.     }
  143.  
  144.     /*
  145.      * Get the best attributes from the server?
  146.      */
  147.     if (f <= 0) {
  148.     AudioAttributes    *bestAttr;
  149.  
  150.     bestAttr = ABestAudioAttributes(audio);
  151.     freq = bestAttr->attr.sampled_attr.sampling_rate;
  152.     } else
  153.     freq = f;
  154.  
  155.     PlayAttribs.attr.sampled_attr.sampling_rate = freq;
  156.     PlayAttribsMask |= ASSamplingRateMask;
  157.  
  158.     Attribs.attr.sampled_attr.sampling_rate = freq;
  159.     AttribsMask |= ASSamplingRateMask;
  160.  
  161.     AChooseSourceAttributes(audio, NULL, NULL, AFFRawLin16,
  162.                 AttribsMask, &Attribs, &seekOffset,
  163.                 &data_length, &byte_order, NULL);
  164.  
  165.     AChoosePlayAttributes(audio, &Attribs, PlayAttribsMask,
  166.               &PlayAttribs, &play_byte_order, NULL);
  167.  
  168.     /*
  169.      * Prepare for conversion.
  170.      * Must remember to free convert_params by calling AEndConversion.
  171.      */
  172.     convert_params = ASetupConversion(audio, &Attribs, &byte_order,
  173.                       &PlayAttribs, &play_byte_order, NULL);
  174.  
  175.     /*
  176.      * Use the external jack, unless the user overrides this on the
  177.      * command-line, or SPEAKER is set.  (The command line stuff is done in
  178.      * main.c.)
  179.      */
  180.     {
  181.       char *speaker;
  182.       if ((speaker = getenv("SPEAKER")) != NULL) {
  183.         if ((*speaker == 'i') || (*speaker == 'I')) {
  184.             use_speaker = 1;
  185.         }
  186.       }
  187.     }
  188.  
  189.     switch (PlayAttribs.attr.sampled_attr.channels) {
  190.  
  191.     case 1:    /* Mono */
  192.     gainEntry[0].u.o.out_ch = AOCTMono;
  193.     gainEntry[0].gain = volume;
  194.     gainEntry[0].u.o.out_dst
  195.         = (use_speaker) ? AODTMonoIntSpeaker : AODTMonoJack;
  196.     break;
  197.  
  198.     case 2:    /* Stereo */
  199.     default:
  200.     gainEntry[0].u.o.out_ch = AOCTLeft;
  201.     gainEntry[0].gain = volume;
  202.     gainEntry[0].u.o.out_dst
  203.         = (use_speaker) ? AODTLeftIntSpeaker : AODTLeftJack;
  204.     gainEntry[1].u.o.out_ch = AOCTRight;
  205.     gainEntry[1].gain = volume;
  206.     gainEntry[1].u.o.out_dst
  207.         = (use_speaker) ? AODTRightIntSpeaker : AODTRightJack;
  208.     break;
  209.     }
  210.     streamParams.gain_matrix.type = AGMTOutput;    /* gain matrix */
  211.     streamParams.gain_matrix.num_entries
  212.     = PlayAttribs.attr.sampled_attr.channels;
  213.     streamParams.gain_matrix.gain_entries = gainEntry;
  214.     streamParams.play_volume = AUnityGain;    /* play volume */
  215.     streamParams.priority = APriorityNormal;    /* normal priority */
  216.     streamParams.event_mask = 0;        /* don't solicit any events */
  217.  
  218.     /*
  219.      * Create an audio stream.
  220.      */
  221.     create_playstream();
  222.  
  223.     /*
  224.      * Calculate the required buffer size for the data prior to conversion
  225.      * and allocate memory for the pre-converted data.
  226.      */
  227.     inLen = ACalculateLength(audio, audio->block_size,
  228.                  &PlayAttribs, &Attribs, NULL); 
  229.     buffer16 = malloc(inLen);
  230.     idx = 0;
  231.  
  232.     /*
  233.      * Allocate a buffer for the converted data.
  234.      */
  235.     bufBase = malloc(inLen);
  236.  
  237.     /*
  238.      * Start stream paused so we can transfer enough data (3 seconds worth)
  239.      * before playing starts to prevent stream from running out.
  240.      */
  241.     APauseAudio(audio, xid, NULL, NULL);
  242.     pauseCount = 3
  243.         * PlayAttribs.attr.sampled_attr.channels
  244.         * PlayAttribs.attr.sampled_attr.sampling_rate
  245.         * (PlayAttribs.attr.sampled_attr.bits_per_sample >> 3);
  246.     audioPaused = True;
  247.  
  248.     freq = PlayAttribs.attr.sampled_attr.sampling_rate;
  249.  
  250.     if (freq != f)
  251.         {
  252.         static char buf[50];
  253.         sprintf(buf, "Frequency used is %d\n", freq);
  254.         notice(buf);
  255.         }
  256.  
  257.      set_mix(30);
  258.  
  259.     return freq;
  260. }
  261.  
  262.  
  263. void output_samples(left, right, n)
  264. int left, right, n;
  265.     {
  266.    if (idx > inLen - 2)
  267.         flush_buffer();
  268.  
  269.     add_samples16(left, right, n);
  270.     }
  271.  
  272.  
  273. void discard_buffer()
  274. {
  275.     /*
  276.      * Destroy old playstream.
  277.      */
  278.     AStopAudio(audio, xid, ASMThisTrans, NULL, NULL);
  279.     close(streamSocket);
  280.     streamSocket = 0;
  281.  
  282.     /*
  283.      * Recreate new playstream.
  284.      */
  285.     create_playstream();
  286.     idx = 0;
  287. }
  288.  
  289.  
  290. void flush_buffer()
  291. {
  292.     int        len_written = 0, len, bytes_written, bytes_read;
  293.     short    *buf = buffer16;
  294.  
  295.     /*
  296.      * Convert buffer
  297.      */
  298.     AConvertBuffer(audio, convert_params, buffer16, idx * sizeof(short),
  299.            bufBase, inLen, &bytes_read, &bytes_written, NULL);
  300.     len = bytes_written;
  301.     buf = bufBase;    
  302.  
  303.     /*
  304.      * Write the converted data to the stream socket
  305.      */
  306.     while (len) {
  307.         /*
  308.      * write converted data to stream socket until we have emptied buffer
  309.      */
  310.     if ((len_written = write(streamSocket, buf, len)) < 0) {
  311.         end_all("Write failed");
  312.         }
  313.     buf += len_written;
  314.     len -= len_written;
  315.  
  316.     if (audioPaused) {
  317.         pauseCount -= len_written;
  318.         if (len_written == 0 || pauseCount <= 0) {
  319.         AResumeAudio(audio, xid, NULL, NULL);
  320.         audioPaused = False;
  321.         }
  322.     }
  323.     }
  324.     idx = 0;
  325. }
  326.  
  327.  
  328. void close_audio()
  329. {
  330.     int        bytes_written;
  331.  
  332.  
  333.     if (audioPaused) {
  334.     AResumeAudio(audio, xid, NULL, NULL);
  335.     }
  336.     /*
  337.      * Free the convert_params structure and flush out
  338.      * the conversion pipeline
  339.      */
  340.     AEndConversion(audio, convert_params, bufBase,
  341.            audio->block_size, &bytes_written, NULL);
  342.  
  343.     ASetCloseDownMode(audio, AKeepTransactions, NULL);
  344.     ASetErrorHandler(prevHandler);
  345.     ACloseAudio(audio, NULL);
  346.  
  347.     if (streamSocket)    close(streamSocket);
  348.     if (buffer16)        free(buffer16);
  349.     if (bufBase)    free(bufBase);
  350.  
  351.     end_all(0);
  352. }
  353.  
  354.  
  355. int update_frequency()
  356. {
  357.     /* not implemented */
  358.     return 0;
  359. }
  360.  
  361.  
  362. void set_synchro(sync)
  363. int sync;
  364. {
  365. /*    if (streamSocket) {
  366.     if (sync)
  367.         setsockopt(streamSocket, SOL_SOCKET, TCP_NODELAY, 1);
  368.     else
  369.         setsockopt(streamSocket, SOL_SOCKET, TCP_NODELAY, 0);
  370.     }*/
  371. }
  372.